// Author: James Gray
// Provides various methods to process and edit sound files.

import java.io.*;
import java.util.*;

public class SoundEditor {
	public static void main(String[] args) {
			
	}
	
	// increases or decreases volume based on if factor is > 1 or factor is < 1, respectively
	public static void adjustVolume(double[] samples, int startIndex, int endIndex, double factor) {
		
		if(endIndex > samples.length) {
			endIndex -= (endIndex - samples.length);
		}
		
		for(int i = startIndex; i <= endIndex; i++) {
			samples[i] *= factor;	
		}
		
		System.out.println(Arrays.toString(samples));

	}

	// mixes two sounds together
	public static void add(double[] samples1, double[] samples2) {
	
		// new version of samples1 in the case of samples2 having a greater length than samples1
		double[] samples1extended = new double[samples2.length];
		
		// used to find the maximum & minimum values for scaling
		double max = 0.0;
		double min = 0.0;
		double scaleFactor;
		
		// first part in the case of samples1.length > samples2.length
		if(samples1.length > samples2.length) {
			for(int i = 0; i < samples2.length; i++) {
				samples1[i] = samples1[i] + samples2[i];
				
				if(samples1[i] > max) {
					max = samples1[i];
				}
				
				if(samples1[i] < min) {
					min = samples1[i];
				}
			}
			
			if(min * (-1) < max) {
				scaleFactor = max;
			} else {
				scaleFactor = min * (-1);
			}
			
			for(int i = 0; i < samples1.length; i++) {
				samples1[i] = samples1[i] / scaleFactor;
			}
			
			System.out.println(Arrays.toString(samples1));

		} else { // 2nd part in the case of samples2.length > samples1.length

			for(int i = 0; i < samples1.length; i++) {
				samples1extended[i] = samples1[i] + samples2[i];
				if(samples1extended[i] > max) {
					max = samples1extended[i];
				}
				
				if(samples1extended[i] < min) {
					min = samples1extended[i];
				}
			}
			
			// requires an extra for loop to copy the values of samples2
      // into the end of samples1extended's array
			for(int i = samples1.length; i < samples1extended.length; i++) {
				samples1extended[i] = samples2[i];
				if(samples1extended[i] > max) {
					max = samples1extended[i];
				}
				
				if(samples1extended[i] < min) {
					min = samples1extended[i];
				}
					
			}
			
			if(min * (-1) < max) {
				scaleFactor = max;
			} else {
				scaleFactor = min * (-1);
			}
			
			// scales values to be within 1 and -1
			for(int i = 0; i < samples1extended.length; i++) {
				samples1extended[i] = samples1extended[i] / scaleFactor;
			}
			
			System.out.println(Arrays.toString(samples1extended));
		}

	}
	
	// reverses the values of the samples array and then prints
	public static void reverse(double[] samples) {
		for (int i = 0; i < samples.length / 2; i++) {	
			// chooses a corresponding index "j" for "i" 
      // for example, if "i" was 3, "j" would be 3 from the end of the array
			int j = samples.length - i - 1;
			
			// stores the value at samples[i] to be placed in samples[j], 
      // then switches the values of samples[i] and samples[j] 
			double temp = samples[i];
			samples[i] = samples[j];
			samples[j] = temp;
		}
		System.out.println(Arrays.toString(samples));
	}
	
	public static void splice(double[] source, int sourceStart, int sourceStop, double[] destination, int destStart) {
		
		// makes sure sourceStop is within the bounds of source.length
		if (sourceStop > (source.length - 1)) {
			sourceStop = (source.length - 1);
		}	
		
		// integer representing the length of the segment to be spliced
		int sourceSegmentLength = (sourceStop - sourceStart) + 1;
		
		// temporary double used for splicing purposes
		double[] temp = new double[sourceSegmentLength];
		
		// gets the values from the source array for the temp
		for(int i = 0; i < temp.length; i++) {
			temp[i] = source[i+sourceStart];
		}
		
		// stores the values from the temp array into the destination array
		for(int i = destStart; i < destStart+sourceSegmentLength; i++) {
			// if statement makes sure the method doesn't try to 
      // update values of the destination array that aren't there
			if (i < destination.length) {
				destination[i] = temp[i-destStart];
			}		
		}
	
		// prints the sound/array as a string
		System.out.println(Arrays.toString(destination));
	
	}
	
	// adjusts the frequency of a sound based on a factor - if the factor is greater than one,
  // the sound will be sped up, and if it is between 0 and 1, the sound will slow down
	public static double[] adjustFrequency(double[] samples, double factor) {
		
		if (factor > 0) {
			
			double[] newSamples = new double[(int)(samples.length / factor)];
			double samplesIndex = 0.0;
			
			for (int i = 0; i < newSamples.length; i++) {
				newSamples[i] = samples[(int)samplesIndex]; 
				samplesIndex = samplesIndex + factor;
			}
			
			return newSamples;
		
		} else {
			
			return null;
		}
		
	}

}
